package com.niiwoo.civet.account.service.dubbo;/**
 * Created by DELL on 2017/12/16.
 */

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.dao.entity.AccountBase;
import com.niiwoo.civet.account.dao.entity.AccountFundTransferOrder;
import com.niiwoo.civet.account.dao.entity.AccountFundTransferOrderExample;
import com.niiwoo.civet.account.dao.entity.BankCard;
import com.niiwoo.civet.account.dao.mapper.AccountFundTransferOrderMapperExt;
import com.niiwoo.civet.account.dto.request.PlateFundTransferRequestDto;
import com.niiwoo.civet.account.dto.request.SubmitAccountFundTransferRequestDTO;
import com.niiwoo.civet.account.dto.response.SubmitAccountFundTransferReponseDTO;
import com.niiwoo.civet.account.enums.AccountFundTransferStatusEnum;
import com.niiwoo.civet.account.service.AccountFundTransferDubboService;
import com.niiwoo.civet.account.service.local.AccountFundTransferService;
import com.niiwoo.civet.account.service.local.AccountService;
import com.niiwoo.civet.account.service.local.BankCardService;
import com.niiwoo.tripod.lanmao.component.LanMaoDirectService;
import com.niiwoo.tripod.lanmao.component.LanMaoSequence;
import com.niiwoo.tripod.lanmao.enums.BusinessTypeEnum;
import com.niiwoo.tripod.lanmao.enums.TransactionTypeEnum;
import com.niiwoo.tripod.lanmao.enums.UserRoleEnum;
import com.niiwoo.tripod.lanmao.request.AsyncTransactionRequest;
import com.niiwoo.tripod.lanmao.request.GroupAccountTransferRequest;
import com.niiwoo.tripod.lanmao.request.QueryTransactionRequest;
import com.niiwoo.tripod.lanmao.response.*;
import com.niiwoo.tripod.provider.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 账户资金划拨
 *
 * @author xiaoyingping
 * @create 2017-12-16 13:00
 **/
@Slf4j
@Service(version = "1.0.0")
public class AccountFundTransferDubboServiceImpl implements AccountFundTransferDubboService {

    @Autowired
    private AccountFundTransferService accountFundTransferService;
    @Autowired
    private AccountFundTransferOrderMapperExt accountFundTransferOrderMapperExt;
    @Autowired
    private AccountService accountService;
    @Autowired
    private LanMaoDirectService lanMaoDirectService;
    @Autowired
    private LanMaoSequence lanMaoSequence;
    @Autowired
    private BankCardService bankCardService;


    public SubmitAccountFundTransferReponseDTO submitFundTransfer(SubmitAccountFundTransferRequestDTO request) {
        log.info("submitFundTransfer start:{}", request);
        SubmitAccountFundTransferReponseDTO result = null;

        String userId = request.getUserId();
        UserRoleEnum payAccountUserRole = request.getPayAccountUserRole();
        UserRoleEnum receiveAccountUserRole = request.getReceiveAccountUserRole();
        BigDecimal amount = request.getAmount();

        Assert.hasLength(userId, "userId不能为空");
        Assert.notNull(payAccountUserRole, "payAccountUserRole");
        Assert.notNull(receiveAccountUserRole, "receiveAccountUserRole不能为空");
        Assert.notNull(amount, "amount不能为空");
        Assert.isTrue(amount.compareTo(BigDecimal.ZERO) > 0, "amount要大于0");

        //判断账户是否存在
        AccountBase payAccount = accountService.loadNiiwooAccount(userId, payAccountUserRole);
        AccountBase receiveAccount = accountService.loadNiiwooAccount(userId, receiveAccountUserRole);

        //判断转出账户的资金是否足够
        if (amount.compareTo(payAccount.getAvailableAmount()) > 0) {
            throw new BizException("ACC10007");
        }

        //生成资金划拨订单
        AccountFundTransferOrder accountFundTransferOrder = new AccountFundTransferOrder();
        accountFundTransferOrder.setUserId(userId);
        accountFundTransferOrder.setAmount(amount);
        accountFundTransferOrder.setPayAccountId(payAccount.getId());
        accountFundTransferOrder.setPayAccountRole(payAccount.getAccountRole());
        accountFundTransferOrder.setPayAccountNo(payAccount.getAccountNo());
        accountFundTransferOrder.setReceiveAccountId(receiveAccount.getId());
        accountFundTransferOrder.setReceiveAccountRole(receiveAccount.getAccountRole());
        accountFundTransferOrder.setReceiveAccountNo(receiveAccount.getAccountNo());
        accountFundTransferService.insertAccountFundTransferOrder(accountFundTransferOrder);

        //向存管银行发起划拨请求
        GroupAccountTransferRequest groupAccountTransferRequest = new GroupAccountTransferRequest();
        groupAccountTransferRequest.setRequestNo(accountFundTransferOrder.getRequestNo());
        groupAccountTransferRequest.setAmount(accountFundTransferOrder.getAmount().toString());
        groupAccountTransferRequest.setPlatformUserNo(payAccount.getAccountNo());
        groupAccountTransferRequest.setReceiverNo(receiveAccount.getAccountNo());
        log.info("调用懒猫用户账户资金划拨接口request:{}", request);
        CompletableFuture<GroupAccountTransferReponse> future = lanMaoDirectService.groupAccountTransfer(groupAccountTransferRequest);

        GroupAccountTransferReponse response = null;
        try {
            response = future.get();
            if (Objects.nonNull(response)) {
                log.info("调用懒猫用户账户资金划拨接口response:{}", JSON.toJSONString(response));
                if (response.isSuccess()) {
                    //划拨成功
                    result = accountFundTransferService.processSubmitFundTransferNotify(accountFundTransferOrder.getId(), true);
                } else {
                    //划拨失败
                    log.error("资金划拨失败,orderId:{}, response:{}", accountFundTransferOrder.getId(), Optional.ofNullable(response).get());
                    result = accountFundTransferService.processSubmitFundTransferNotify(accountFundTransferOrder.getId(), false);
                }
            }else{
                log.info("调用懒猫用户账户资金划拨接口response:null");
            }
        } catch (Exception e) {
            log.error("调用懒猫用户账户资金划拨接异常", e);
            result = new SubmitAccountFundTransferReponseDTO();
            result.setTransferSuccess(false);
        }

        //返回
        return result;
    }


    @Override
    public void processSubmitFundTransferNotify(String requestNo, Boolean isTansferSuccess) {
        Assert.hasLength(requestNo, "requestNo不能为空");
        Assert.notNull(isTansferSuccess, "isTansferSuccess不能为空");

        AccountFundTransferOrder accountFundTransferOrder = accountFundTransferService.loadByRequestNo(requestNo);
        accountFundTransferService.processSubmitFundTransferNotify(accountFundTransferOrder.getId(), isTansferSuccess);
    }


    public void queryGroupAccountTransferJob() {
        //定时job，十分钟以内的不调用接口查询
        Date endQueryDate = new DateTime().minusSeconds(60 * 10).toDate();
        //查询正在处理中的资金划拨订单
        AccountFundTransferOrderExample example = new AccountFundTransferOrderExample();
        AccountFundTransferOrderExample.Criteria criteria = example.createCriteria();
        criteria.andStatusEqualTo(AccountFundTransferStatusEnum.HANDLING.getValue());
        List<AccountFundTransferOrder> accountFundTransferOrderList = accountFundTransferOrderMapperExt.selectByExample(example);
        List<AccountFundTransferOrder> list = accountFundTransferOrderList.stream().filter(e -> e.getCreateTime().before(endQueryDate)).collect(Collectors.toList());
        log.info("queryGroupAccountTransferJob size:{}", list.size());

        for (AccountFundTransferOrder accountFundTransferOrder : list) {
            //向懒猫查询订单的状态
            String requestNo = accountFundTransferOrder.getRequestNo();
            String payAccountNo = accountFundTransferOrder.getPayAccountNo();
            if(StringUtils.isEmpty(accountFundTransferOrder.getBatchNo())){
                log.info("调用懒猫查询用户账户资金划拨接口requestNo:{}, accountNo:{}", requestNo, payAccountNo);
                CompletableFuture<QueryGroupAccountTransferResponse> future = lanMaoDirectService.queryGroupAccountTransfer(requestNo, payAccountNo);
                try {
                    QueryGroupAccountTransferResponse response = future.get();
                    transterAccount(accountFundTransferOrder, requestNo, payAccountNo, response);
                } catch (Exception e) {
                    log.error("调用懒猫查询用户账户资金划拨接口异常", e);
                }
            }else{
                QueryTransactionRequest request = new QueryTransactionRequest();
                request.setPlatformUserNo(payAccountNo);
                request.setRequestNo(requestNo);
                log.info("调用懒猫查询用户账户资金划拨接口requestNo:{}, accountNo:{}", requestNo, payAccountNo);
                CompletableFuture<QueryTransactionResponse> future = lanMaoDirectService.queryTransaction(request);
                try {
                    QueryTransactionResponse response = future.get();
                    transterAccount(accountFundTransferOrder, requestNo, payAccountNo, response);
                } catch (Exception e) {
                    log.error("调用懒猫查询用户账户资金划拨接口异常", e);
                }
            }


        }
    }

    private void transterAccount(AccountFundTransferOrder accountFundTransferOrder, String requestNo, String payAccountNo, LanMaoResponse response) {
        if (Objects.nonNull(response)) {
            log.info("调用懒猫查询用户账户资金划拨接口requestNo:{}, accountNo:{}, response:{}", requestNo, payAccountNo, JSON.toJSONString(response));
            if (response.isSuccess()) {
                //交易成功
                accountFundTransferService.processSubmitFundTransferNotify(accountFundTransferOrder.getId(), true);
            } else {
                //交易不成功
                accountFundTransferService.processSubmitFundTransferNotify(accountFundTransferOrder.getId(), false);
            }
        } else {
            //交易不存在
            log.info("调用懒猫查询用户账户资金划拨接口requestNo:{}, accountNo:{}, response:{}", requestNo, payAccountNo, null);
            accountFundTransferService.processSubmitFundTransferNotify(accountFundTransferOrder.getId(), false);
        }
    }


    public SubmitAccountFundTransferReponseDTO submitPlateFundTransfer(PlateFundTransferRequestDto requestDTO) {
        log.info("submitFundTransfer start:{}", requestDTO);
        SubmitAccountFundTransferReponseDTO result = null;

        String userId = requestDTO.getUserId();
        UserRoleEnum payAccountUserRole = requestDTO.getPayAccountUserRole();
        UserRoleEnum receiveAccountUserRole = requestDTO.getReceiveAccountUserRole();
        BigDecimal amount = requestDTO.getAmount();

        Assert.notNull(userId, "userId不能为空");
        Assert.notNull(payAccountUserRole, "payAccountUserRole");
        Assert.notNull(receiveAccountUserRole, "receiveAccountUserRole不能为空");
        Assert.notNull(amount, "amount不能为空");
        Assert.isTrue(amount.compareTo(BigDecimal.ZERO) > 0, "amount要大于0");

        //判断账户是否存在
        AccountBase payAccount = accountService.loadNiiwooAccount(userId, payAccountUserRole);
        AccountBase receiveAccount = accountService.loadNiiwooAccount(userId, receiveAccountUserRole);
        Assert.notNull(payAccount, "转出账户不存在");
        Assert.notNull(receiveAccount, "转入账户不存在");
        if (Byte.valueOf("0").equals(payAccount.getImportUserActiva())) {
            throw new BizException("ACC10003");// 存管账户未激活
        }
        if (Byte.valueOf("0").equals(receiveAccount.getImportUserActiva())) {
            throw new BizException("ACC10003");// 存管账户未激活
        }
        //查询用户银行卡信息
        BankCard bankCard = bankCardService.getSimpleUserBankCard(payAccount.getUserId());
        if (bankCard == null) {
            throw new BizException("ACC10012");
        }
        //判断转出账户的资金是否足够
        if (amount.compareTo(payAccount.getAvailableAmount()) > 0) {
            throw new BizException("ACC10007");
        }
        String batchNo = lanMaoSequence.getBatchNo();
        //生成资金划拨订单
        AccountFundTransferOrder accountFundTransferOrder = new AccountFundTransferOrder();
        accountFundTransferOrder.setUserId(userId);
        accountFundTransferOrder.setAmount(amount);
        accountFundTransferOrder.setPayAccountId(payAccount.getId());
        accountFundTransferOrder.setPayAccountRole(payAccount.getAccountRole());
        accountFundTransferOrder.setPayAccountNo(payAccount.getAccountNo());
        accountFundTransferOrder.setReceiveAccountId(receiveAccount.getId());
        accountFundTransferOrder.setReceiveAccountRole(receiveAccount.getAccountRole());
        accountFundTransferOrder.setReceiveAccountNo(receiveAccount.getAccountNo());
        accountFundTransferOrder.setBatchNo(batchNo);
        accountFundTransferService.insertAccountFundTransferOrder(accountFundTransferOrder);

        // 银行存管业务明细
        List<AsyncTransactionRequest.BizDetail.BusinessDetail> businessDetailList = new ArrayList<>();
        // 生成存管业务明细
        AsyncTransactionRequest.BizDetail.BusinessDetail businessDetail = new AsyncTransactionRequest.BizDetail.BusinessDetail();
        businessDetail.setBizType(BusinessTypeEnum.FUNDS_TRANSFER);
        businessDetail.setSourcePlatformUserNo(payAccount.getAccountNo());
        businessDetail.setTargetPlatformUserNo(receiveAccount.getAccountNo());
        businessDetail.setAmount(amount);
        businessDetail.setRemark(requestDTO.getRemark());
        businessDetailList.add(businessDetail);
        AsyncTransactionRequest.BizDetail bizDetail = new AsyncTransactionRequest.BizDetail();
        bizDetail.setRequestNo(accountFundTransferOrder.getRequestNo());
        bizDetail.setTradeType(TransactionTypeEnum.FUNDS_TRANSFER);
        bizDetail.setDetails(businessDetailList);

        List<AsyncTransactionRequest.BizDetail> bizDetailList = new ArrayList<>();
        bizDetailList.add(bizDetail);

        AsyncTransactionRequest asyncTransactionRequest = new AsyncTransactionRequest();
        asyncTransactionRequest.setBatchNo(batchNo);
        asyncTransactionRequest.setBizDetails(bizDetailList);
        // 调用银行存管资金划拨
        CompletableFuture<AsyncTransactionResponse> future = lanMaoDirectService.asyncTransaction(asyncTransactionRequest);
        try {
            AsyncTransactionResponse response = future.get();
            if (Objects.nonNull(response)) {
                log.info("调用懒猫平台账户资金划拨接口response:{}", JSON.toJSONString(response));
                result = new SubmitAccountFundTransferReponseDTO();
                if (response.isSuccess()) {
                    result.setTransferSuccess(true);
                    //转账成功
                    //result = accountFundTransferService.processSubmitFundTransferNotify(accountFundTransferOrder.getId(), true);
                } else {
                    result.setTransferSuccess(false);
                    //转账失败
                    //result = accountFundTransferService.processSubmitFundTransferNotify(accountFundTransferOrder.getId(), false);
                }
            }else {
                log.info("调用懒猫平台账户资金划拨接口response:null");
            }
        } catch (Exception e) {
            log.error("调用懒猫平台账户资金划拨接口异常", e);
            result = new SubmitAccountFundTransferReponseDTO();
            result.setTransferSuccess(false);
        }

        return result;

    }

}
